package org.exteen.output;

import java.io.Writer;


public class NiceXmlExteenStream extends ExteenStream {

    private final String indentString;
    private final String newLine = "\n";
    private final StringBuilder textCache = new StringBuilder();

    private int indent = 0;
    private String recentlyOpenedTag = "";
    private boolean wasNewLineAsLast = true;

    public NiceXmlExteenStream(Writer writer, String indentString) {
        super(writer);
        this.indentString = indentString;
    }

    private void printIndent() {
        if (indent == 0) {
            return;
        }
        if (indent < 3) {
            for (int i = 0; i < indent; i++) {
                this.writer.print(indentString);
            }
            return;
        }
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < indent; i++) {
            sb.append(indentString);
        }
        this.writer.print(sb.toString());
    }

    public void printTagOpen(String tagName) {
        flushTextCache(false);
        if (!wasNewLineAsLast) {
            writer.print(newLine);
        }
        printIndent();
        super.printTagOpen(tagName);
        indent++;
        recentlyOpenedTag = tagName;
        wasNewLineAsLast = false;
    }

    public void printTagClose(String tagName) {
        flushTextCache(recentlyOpenedTag.equals(tagName));
        indent--;
        if (!recentlyOpenedTag.equals(tagName)) {
            if (!wasNewLineAsLast) {
                writer.print(newLine);
            }
            printIndent();
        } else {
            recentlyOpenedTag = "";
        }
        super.printTagClose(tagName);
        wasNewLineAsLast = false;
    }

    public void printText(String string) {
        textCache.append(string);
    }

    private void flushTextCache(boolean keepBlanks) {
        if (textCache.length() == 0) {
            return;
        }
        String string = textCache.toString();
        if (keepBlanks) {
            this.writer.print(string);
            wasNewLineAsLast = true;
            textCache.setLength(0);
            return;
        }
        wasNewLineAsLast = false;
        String trimmed = string.trim();
        if (trimmed.length()==0) {
            // only one
            if (string.startsWith(newLine)) {
                this.writer.print(newLine);
                wasNewLineAsLast = true;
            } else {
                this.writer.print(string.substring(0, 1));
            }
        } else {
            // left
            if (trimmed.charAt(0) != string.charAt(0)) {
                if (string.startsWith(newLine)) {
                    this.writer.print(newLine);
                } else {
                    this.writer.print(string.substring(0, 1));
                }
            }
            this.writer.print(trimmed);
            // right
            if (trimmed.charAt(trimmed.length() - 1) != string.charAt(string.length() - 1)) {
                if (string.endsWith(newLine)) {
                    this.writer.print(newLine);
                    wasNewLineAsLast = true;
                } else {
                    this.writer.print(string.substring(string.length() - 1));
                }
            }
        }
        textCache.setLength(0);
    }

    public void flush() {
        flushTextCache(false);
        super.flush();
    }
}
